/* Autostop - camera driver
 *
 * Copyright (c) Maciej Gajewski, Grzegorz Latarowski
 * http://code.google.com/p/autostop-automaty-drogowe
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
 */

#include <QDataStream>
#include "viewerwindow.h"

ViewerWindow::ViewerWindow(QWidget *parent)
 : QWidget(parent)
{
	setupUi( this );

	connect( &_socket, SIGNAL(readyRead()), SLOT(socketDataReady()) );
	connect( &_socket, SIGNAL( stateChanged ( QAbstractSocket::SocketState )),
		SLOT(socketStateChanged( QAbstractSocket::SocketState ) ) );

	_state = WaitingForHeader;
	_playing = false;
	_request = 0;
}


ViewerWindow::~ViewerWindow()
{
	// empty
}

// -------------------- on_butonPlay_clicked -----------------------
void ViewerWindow::on_buttonPlay_clicked()
{
	if ( _playing )
	{
		_playing = false;
		buttonPlay->setText( tr("Play") );
	}
	else
	{
		_playing = true;
		buttonPlay->setText( tr("Stop") );
		requestFrame();
	}
}

// -------------------- on_buttonConnect_clicket -----------------------
void ViewerWindow::on_buttonConnect_clicked()
{
	if ( _socket.state() == QAbstractSocket::UnconnectedState )
	{
		_socket.connectToHost( editAddress->text(), 5102 );
	}
}

// ---------------------- socketStateChanged --------------------------
void ViewerWindow::socketStateChanged( QAbstractSocket::SocketState socketState )
{
	switch( socketState )
	{		
		case QAbstractSocket::UnconnectedState:
			Log("Socket: unconnected");
			break;
		case QAbstractSocket::HostLookupState:
			Log("Socket: host lookup");
			break;
		case QAbstractSocket::ConnectingState:
			Log("Socket: connecting");
			break;
		case QAbstractSocket::ConnectedState:
			Log("Socket: connected");
			break;
		case QAbstractSocket::ClosingState:
			Log("Socket: closing");
			break;
		
		default:
		case QAbstractSocket::BoundState:
		case QAbstractSocket::ListeningState:
			Log("Socket: other state");

	}// sw
}

// ---------------------- socketStateChanged --------------------------
void ViewerWindow::socketDataReady()
{
	if ( _state == WaitingForHeader )
	{
		// read header
		readHeader();
	}
	else
	{
		// collect data here
		readData();
	}
}

// ---------------------- Log --------------------------
void ViewerWindow::Log( const QString& text )
{
	textLog->append( text );
}

// ---------------------- readHeader --------------------------
void ViewerWindow::readHeader()
{
	int headerSize = sizeof( quint32 );
	
	if ( _socket.bytesAvailable() >= headerSize )
	{
		QDataStream stream( &_socket );
		
		int frameSize = 0;
		stream >> frameSize;
		// header readed - switxch to data read state
		_state = CollectingData;
		_data.clear();
		_data.reserve( frameSize );
		_bytesToRead = frameSize;
	
		// try read some data
		readData();
		
		// request next frame, if playing
		if ( _playing )
		{
			requestFrame();
		}
	}
}

// ---------------------- readData --------------------------
void ViewerWindow::readData()
{
	quint64 bytesAvailable = _socket.bytesAvailable();
	
	if ( bytesAvailable > 0 )
	{
		quint64 bytesToRead = qMin( bytesAvailable, _bytesToRead );
		_data += _socket.read( bytesToRead );
		_bytesToRead -= bytesToRead;
		
		// all data read - handle and switch to header mode
		if ( _bytesToRead == 0 )
		{
			dataReaded();	// handle frame data
			_state = WaitingForHeader;
			
			// try read header out of remaining bytes
			readHeader();
			// TODO request next frame here
		}
		
	}
}

// ---------------------- dataReaded --------------------------
void ViewerWindow::dataReaded()
{
	// disabled to improve performance
	//Log( QString("Frame get: %1 bytes").arg( _data.size() ) );
	
	// read and decode image
	QDataStream stream( _data );
	
	int width;
	int height;
	QByteArray imageData;
	
	stream >> width;
	stream >> height;
	stream >> imageData;
	
	QImage image( width, height, QImage::Format_RGB32 );
	
	char* byte = imageData.data();
	for( int y = 0; y < height; y++ )
	{
		for( int x = 0; x< width; x++ )
		{
			if ( byte< imageData.data() + imageData.size()  )
			{
				image.setPixel( x, y, qRgb( *byte, *byte, *byte ) );
				byte++;
			}
		}
	}
	
	labelImage->setPixmap( QPixmap::fromImage( image ) );
}


// ---------------------- requestFrame --------------------------
void ViewerWindow::requestFrame()
{
	if ( _socket.state() = QTcpSocket::Connected )
	{
		// the request5 is just 32 bit integer. no interpretation for now
		quint32 request = _request++;
		
		QDataStream( & _socket ) << request;
		_socket.waitForBytesWritten( 100 );
		
		//disbaled to improve performace
		//Log( QString("Request sent (%1)").arg( request) );
	}
}

// ---------------------- socketError --------------------------
void ViewerWindow::socketError()
{
	Log( QString("Socket error: %1").arg( _socket.errorString() ) );
}

// eof 


